
#ifndef __BMANX_BOMBERLEAGUE_MENU__HEADER_FILE__
#define __BMANX_BOMBERLEAGUE_MENU__HEADER_FILE__


#include "globals.h"

////////////////////////////////////////////////////////////////////////////////
struct Menu
{
    void set_escape_code( const token& esc )
    {
        _escape = esc;
    }

    uint add_entry( const token& text )
    {
        token t = text;
        token alt = t.cut_left('|',1,true);
        if(alt.is_empty())
            alt = text;

        uint pos = _entries.size();
        Entry* pe = _entries.add();
        pe->text = text;
        pe->key = alt;
        pe->typ = ET_SELECTABLE;
        pe->x = _x;
        pe->y = _y;
        _y += 48;
        return pos;
    }

    uint add_checkbox( const token& text, int* val )
    {
        uint pos = add_entry( text );
        Entry* pe = _entries.last();
        pe->typ = ET_CHECKBOX;
        pe->val = val;
        return pos;
    }

    uint add_bar( uint rgb, const token& text, uchar* val )
    {
        uint pos = add_entry( text );
        Entry* pe = _entries.last();
        pe->typ = ET_BAR_R + rgb;
        pe->val = val;
        return pos;
    }

    typedef bool (*fnc_accept_char)( int, charstr&, uint );
    static bool accept_alpha( int key, charstr&, uint )   { return (key>='a' && key<='z') || (key>='A' && key<='Z'); }
    static bool accept_nick( int key, charstr&, uint )
    {   return (key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z') || (key >= '0' && key <= '9')
            || key == '_' || key == ' ' || key == '-' || key == '.';
    }
    static bool accept_ip( int key, charstr&, uint )
    {   return (key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z') || (key >= '0' && key <= '9')
            || key == '-' || key == '.';
    }

    uint add_textbox( const token& text, charstr& val, fnc_accept_char fn=0 )
    {
        uint pos = add_entry( text );
        Entry* pe = _entries.last();
        pe->typ = ET_TEXT;
        pe->valstr = &val;
        pe->fnacc = fn;
        return pos;
    }

    void add_space( uint pix )
    {
        _y += pix;
    }


    Menu()
    {
        _x = 64;
        _y = 64;
        _active = 0;

        _selp = UMAX;
        _sell = 0;
        _escape = token::empty();
    }


    void draw()
    {
        for( uint i=0; i<_entries.size(); ++i )
        {
            const Entry& en = _entries[i];
            token t = en.text;
            if( en.key.len() < t.len() )  t += 1+en.key.len();
            FONT.print( SCREEN, en.x, en.y, t );

            if( _selimage && i == _active )
            {
                uint fr = _Timer.time() / 64;
                fr %= _selimage->_array.size() / 2;
                SCREEN.draw_colorize( _selimage->_array[fr], 0, _colpri, _colsec, 8, en.y );
            }
            //else
            //    SCREEN.fill( 8, en.y, 48, 48, 0 );

            bool bar=false;
            uint32 major,minor;
            if( en.typ == ET_BAR_R )        bar=true, major=0x00ff0000, minor=0x003f0000;
            else if( en.typ == ET_BAR_G )   bar=true, major=0x0000ff00, minor=0x00003f00;
            else if( en.typ == ET_BAR_B )   bar=true, major=0x000000ff, minor=0x0000003f;

            if(bar) {
                uchar v = *(uchar*)en.val;
                SCREEN.fill( en.x + 256 - 2, en.y+16-2, 256+4, 48-2*16+4, minor );
                SCREEN.fill( en.x + 256, en.y+16, v, 48-2*16, major );
            }
            else if( en.typ == ET_TEXT )
            {
                SCREEN.fill( en.x + 256, en.y, 256, 40, 0x1f1f1f );
                if( i == _active && _selp != UMAX )
                {
                    token tn1( _tmpstr, 0, _selp );
                    token ts( _tmpstr, _selp, _sell );
                    token tn2( _tmpstr, _selp+_sell, UMAX );

                    int x = en.x+256;
                    x = FONT.print( SCREEN, x, en.y, tn1 );
                    
                    if(_sell)
                        SCREEN.fill( x, en.y+1, FONT.text_width(ts), 40-2, 0xefefef );
                    else if( (_Timer.time()%400) < 200 )
                        SCREEN.fill( x, en.y+1, 2, 40-2, 0xefefef );

                    x = FONT.print( SCREEN, x, en.y, ts, true );
                    x = FONT.print( SCREEN, x, en.y, tn2 );
                }
                else
                    FONT.print( SCREEN, en.x+256, en.y, *en.valstr );
            }
            else if( en.typ == ET_CHECKBOX )
            {
                SCREEN.fill( en.x+256, en.y, 40, 40, 0xffffff );
                SCREEN.fill( en.x+256+2, en.y+2, 40-4, 40-4, 0 );

                if( *(int*)en.val )
                    SCREEN.fill( en.x+256+10, en.y+10, 40-20, 40-20, 0xffffff );
            }
        }
    }

    token onkeypress_generic( int key )
    {
        if( key == SDLK_ESCAPE )
            return _escape;

        if( key == SDLK_DOWN ) {
            if( _active+1 < _entries.size() )  ++_active;
            else _active = 0;
        }
        else if( key == SDLK_UP ) {
            if( _active > 0 )  --_active;
            else _active = _entries.size() - 1;
        }
        else if( key == SDLK_RETURN )
            return _entries[_active].key;

        return token::empty();
    }

    token onkeypress( int key )
    {
        Entry& en = _entries[_active];

        if( en.typ == ET_CHECKBOX )
        {
            if( key == SDLK_RETURN  ||  key == SDLK_LEFT  ||  key == SDLK_RIGHT ) {
                *(int*)en.val = !*(int*)en.val;
                return token::empty();
            }
        }
        else if( en.typ == ET_TEXT )
        {
            if( key == SDLK_UP  ||  key == SDLK_DOWN ) {
                if( is_textedit_mode() )
                    set_textedit_mode(0);
                return onkeypress_generic(key);
            }
            else if( key == SDLK_RETURN ) {
                if( !is_textedit_mode() )
                    set_textedit_mode(1);
                else
                    set_textedit_mode(0);
                return token::empty();
            }
            else if( key == SDLK_ESCAPE ) {
                if( is_textedit_mode() ) {
                    set_textedit_mode(-1);
                    return token::empty();
                }
                else
                    return onkeypress_generic(key);
            }

            if( !is_textedit_mode() )
                return onkeypress_generic(key);

            if( key == SDLK_RIGHT ) {
                if(_sell) _selp += _sell, _sell=0;
                else if( _selp<_tmpstr.len() ) ++_selp;
            }
            else if( key == SDLK_LEFT ) {
                if(_sell) _sell=0;
                else if( _selp>0 ) --_selp;
            }
            else if( key == SDLK_END ) {
                _selp = _tmpstr.len();
                _sell = 0;
            }
            else if( key == SDLK_HOME ) {
                _selp = 0;
                _sell = 0;
            }
            else if( key == SDLK_DELETE ) {
                _tmpstr.del( _selp, _sell ? _sell : 1 );
                _sell = 0;
            }
            else if( key == SDLK_BACKSPACE ) {
                if(_sell)
                    _tmpstr.del( _selp, _sell );
                else if( _selp>0 ) {
                    --_selp;
                    _tmpstr.del( _selp, 1 );
                }
            }
            else
            {
                if(_sell) {
                    _tmpstr.del( _selp, _sell );
                    _sell = 0;
                }

                if( (!en.fnacc && key <= 0x7f) || en.fnacc(key,_tmpstr,_selp) )
                    _tmpstr.ins( _selp++, key );
            }

            return token::empty();
        }
        else if( en.typ >= ET_BAR_R  &&  en.typ <= ET_BAR_B )
        {
            uchar& v = *(uchar*)en.val;
            if( key == SDLK_RIGHT  &&  v < 255 )
                ++v;
            if( key == SDLK_LEFT  &&  v > 0 )
                --v;
        }


        return onkeypress_generic(key);
    }


    static void set_sel_image( TexImage::ColorizedSpriteArray* sel )
    {
        _selimage = sel;
    }

    static void set_sel_colors( uint32 colpri, uint32 colsec )
    {
        _colpri = colpri;
        _colsec = colsec;
    }

protected:

    bool is_textedit_mode() const       { return _selp != UMAX; }

    /// @param tem <0 cancel, 0 ok, >0 enter textedit
    void set_textedit_mode( int tem )
    {
        if(tem>0) {
            _selp=0;
            _sell=_entries[_active].valstr->len();
            _tmpstr = *_entries[_active].valstr;
        }
        else if(tem==0) {
            _entries[_active].valstr->takeover(_tmpstr);
            _selp=UMAX;
        }
        else
            _selp=UMAX;
    }

    struct Entry
    {
        uint x,y;
        token key;
        charstr text;

        void* val;
        charstr* valstr;

        fnc_accept_char fnacc;

        uchar typ;

        Entry()
        {
            val = 0;
            valstr = 0;
            fnacc = 0;
        }
    };

    enum {
        ET_SELECTABLE = 0,
        ET_TEXT,
        ET_CHECKBOX,
        ET_BAR_R, ET_BAR_G, ET_BAR_B,
    };

    dynarray<Entry> _entries;
    uint _active;
    token _escape;

    charstr _tmpstr;

    uint _x,_y;

    uint _selp,_sell;

    static TexImage::ColorizedSpriteArray* _selimage;
    static uint32 _colpri, _colsec;
};

#endif //__BMANX_BOMBERLEAGUE_MENU__HEADER_FILE__
